//-------------------------------------------------------------------
//	Copyright (c) 2010-2012  Zhirnov Andrey
//	This file is part of the "UX Standard Lib" project.
//	See copyright notice in "UX_STL_Ext.h".
//-------------------------------------------------------------------

#ifndef _UX_RENDER_PROFILER_H
#define _UX_RENDER_PROFILER_H

#include <Includes.h>

namespace Engine
{
namespace RenderUtils
{
	
	//
	// Render Profiler Interface
	//

	class _EXPORT_ IRenderProfiler
	{
	public:

#ifdef UX_RENDER_PROFILER_DISABLE

		inline  void Init()								{}
		
		inline  void BeginFrame()						{}
		inline  void EndFrame()							{}
		
		inline  void BeginRenderProfiler(const string &){}
		inline  void EndRenderProfiler()				{}

		inline  uint BeginProfiling(const string &)		{return 0;}
		inline  void EndProfiling(uint)					{}

		inline  void Reset()							{}

		inline  void GetProfilerText(string &)			{}
#else
		virtual void Init() = 0;

		virtual void BeginFrame() = 0;
		virtual void EndFrame() = 0;
		
		virtual void BeginRenderProfiler(const string &sName) = 0;
		virtual void EndRenderProfiler() = 0;

		virtual uint BeginProfiling(const string &sName) = 0;	// return index
		virtual void EndProfiling(uint uIndex) = 0;

		virtual void Reset() = 0;							// reset all timers

		virtual void GetProfilerText(string &sText) = 0;	// calc params and return string

#endif	// UX_RENDER_PROFILER_DISABLE
	};



	//
	// Render Profiler
	//

	class _EXPORT_ CRenderProfiler : public IRenderProfiler
	{
	private:
		struct TUpdateTime
		{
			string		sName;
			float		fTime;		// time in nanoseconds
			bool		bIsDelta;	// set true in End*() function
			///
			TUpdateTime(): fTime(0.f), bIsDelta(false) {}
			TUpdateTime(const string &name, float time): sName(name), fTime(time), bIsDelta(false) {}
		};

		struct TGPUTime
		{
			string		sName;
			float		fTime;		// time in nanoseconds
			bool		bReady;
			///
			TGPUTime(): fTime(0.f), bReady(false) {}
			TGPUTime(const string &name): sName(name), fTime(0.f), bReady(false) {}
		};

		typedef array< TUpdateTime >	updtime_array_t;
		typedef array< TGPUTime >		gputime_array_t;

	private:
		string				_sProfilerText;

		TCriticalSection	_sCSLock;
		TPerfTimer			_sTimer;

		updtime_array_t		_aUpdateTimes;
		gputime_array_t		_aGPUTimes;

		GLQuery				_cPrimitivesQuery,		// generated primitives
							_cRenderTimeQuery;

		uint				_uPrimitives,
							_uMinFPS,
							_uMaxFPS;

		usize				_uMaxLength;
		
		bool				_bChanged	: 1;
		bool				_bRendering	: 1;

	private:
		void _UpdateProfiler();

	public:
		CRenderProfiler();
		~CRenderProfiler();
		
		// IRenderProfiler //
		virtual void Init();
		virtual void Reset();

		virtual void BeginFrame();
		virtual void EndFrame();
		
		virtual void BeginRenderProfiler(const string &sName);
		virtual void EndRenderProfiler();

		virtual uint BeginProfiling(const string &sName);
		virtual void EndProfiling(uint uIndex);

		virtual void GetProfilerText(string &sText);
	};

//-------------------------------------------------------------------

}	// RenderUtils
}	// Engine

#endif	// _UX_RENDER_PROFILER_H